home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 45
/
Aminet 45 (2001)(GTI - Schatztruhe)[!][Oct 2001].iso
/
Aminet
/
gfx
/
x11
/
x3270_3_2_16.lha
/
amiga_src
/
trace_ds.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-06-23
|
21KB
|
997 lines
/*
* Copyright 1993, 1994, 1995, 1999, 2000 by Paul Mattes.
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation.
*/
/*
* trace_ds.c
* 3270 data stream tracing.
*
*/
#include "globals.h"
#if defined(X3270_TRACE) /*[*/
#if defined(X3270_DISPLAY) /*[*/
#include <X11/StringDefs.h>
#include <X11/Xaw/Dialog.h>
#endif /*]*/
#include <errno.h>
#include <signal.h>
#include <time.h>
#include <stdarg.h>
#include <fcntl.h>
#include "3270ds.h"
#include "appres.h"
#include "objects.h"
#include "resources.h"
#include "ctlr.h"
#include "ctlrc.h"
#include "menubarc.h"
#include "popupsc.h"
#include "printc.h"
#include "savec.h"
#include "tablesc.h"
#include "telnetc.h"
#include "trace_dsc.h"
#include "utilc.h"
/* Statics */
static int dscnt = 0;
static int tracewindow_pid = -1;
/* Globals */
FILE *tracef = (FILE *) 0;
struct timeval ds_ts;
Boolean trace_skipping = False;
static const char *
unknown(unsigned char value)
{
static char buf[64];
(void) sprintf(buf, "unknown[0x%x]", value);
return buf;
}
/* display a (row,col) */
const char *
rcba(int baddr)
{
static char buf[16];
(void) sprintf(buf, "(%d,%d)", baddr/COLS + 1, baddr%COLS + 1);
return buf;
}
const char *
see_ebc(unsigned char ch)
{
static char buf[8];
switch (ch) {
case FCORDER_NULL:
return "NULL";
case FCORDER_SUB:
return "SUB";
case FCORDER_DUP:
return "DUP";
case FCORDER_FM:
return "FM";
case FCORDER_FF:
return "FF";
case FCORDER_CR:
return "CR";
case FCORDER_NL:
return "NL";
case FCORDER_EM:
return "EM";
case FCORDER_EO:
return "EO";
}
if (ebc2asc[ch])
(void) sprintf(buf, "%c", ebc2asc[ch]);
else
(void) sprintf(buf, "\\%o", ch);
return buf;
}
const char *
see_aid(unsigned char code)
{
switch (code) {
case AID_NO:
return "NoAID";
case AID_ENTER:
return "Enter";
case AID_PF1:
return "PF1";
case AID_PF2:
return "PF2";
case AID_PF3:
return "PF3";
case AID_PF4:
return "PF4";
case AID_PF5:
return "PF5";
case AID_PF6:
return "PF6";
case AID_PF7:
return "PF7";
case AID_PF8:
return "PF8";
case AID_PF9:
return "PF9";
case AID_PF10:
return "PF10";
case AID_PF11:
return "PF11";
case AID_PF12:
return "PF12";
case AID_PF13:
return "PF13";
case AID_PF14:
return "PF14";
case AID_PF15:
return "PF15";
case AID_PF16:
return "PF16";
case AID_PF17:
return "PF17";
case AID_PF18:
return "PF18";
case AID_PF19:
return "PF19";
case AID_PF20:
return "PF20";
case AID_PF21:
return "PF21";
case AID_PF22:
return "PF22";
case AID_PF23:
return "PF23";
case AID_PF24:
return "PF24";
case AID_OICR:
return "OICR";
case AID_MSR_MHS:
return "MSR_MHS";
case AID_SELECT:
return "Select";
case AID_PA1:
return "PA1";
case AID_PA2:
return "PA2";
case AID_PA3:
return "PA3";
case AID_CLEAR:
return "Clear";
case AID_SYSREQ:
return "SysReq";
case AID_QREPLY:
return "QueryReplyAID";
default:
return unknown(code);
}
}
const char *
see_attr(unsigned char fa)
{
static char buf[256];
const char *paren = "(";
buf[0] = '\0';
if (fa & 0x04) {
(void) strcat(buf, paren);
(void) strcat(buf, "protected");
paren = ",";
if (fa & 0x08) {
(void) strcat(buf, paren);
(void) strcat(buf, "skip");
paren = ",";
}
} else if (fa & 0x08) {
(void) strcat(buf, paren);
(void) strcat(buf, "numeric");
paren = ",";
}
switch (fa & 0x03) {
case 0:
break;
case 1:
(void) strcat(buf, paren);
(void) strcat(buf, "detectable");
paren = ",";
break;
case 2:
(void) strcat(buf, paren);
(void) strcat(buf, "intensified");
paren = ",";
break;
case 3:
(void) strcat(buf, paren);
(void) strcat(buf, "nondisplay");
paren = ",";
break;
}
if (fa & 0x20) {
(void) strcat(buf, paren);
(void) strcat(buf, "modified");
paren = ",";
}
if (strcmp(paren, "("))
(void) strcat(buf, ")");
else
(void) strcpy(buf, "(default)");
return buf;
}
static const char *
see_highlight(unsigned char setting)
{
switch (setting) {
case XAH_DEFAULT:
return "default";
case XAH_NORMAL:
return "normal";
case XAH_BLINK:
return "blink";
case XAH_REVERSE:
return "reverse";
case XAH_UNDERSCORE:
return "underscore";
case XAH_INTENSIFY:
return "intensify";
default:
return unknown(setting);
}
}
#if !defined(X3270_DISPLAY) /*[*/
static
#endif /*]*/
const char *
see_color(unsigned char setting)
{
static const char *color_name[] = {
"neutralBlack",
"blue",
"red",
"pink",
"green",
"turquoise",
"yellow",
"neutralWhite",
"black",
"deepBlue",
"orange",
"purple",
"paleGreen",
"paleTurquoise",
"grey",
"white"
};
if (setting == XAC_DEFAULT)
return "default";
else if (setting < 0xf0 || setting > 0xff)
return unknown(setting);
else
return color_name[setting - 0xf0];
}
static const char *
see_transparency(unsigned char setting)
{
switch (setting) {
case XAT_DEFAULT:
return "default";
case XAT_OR:
return "or";
case XAT_XOR:
return "xor";
case XAT_OPAQUE:
return "opaque";
default:
return unknown(setting);
}
}
static const char *
see_validation(unsigned char setting)
{
static char buf[64];
const char *paren = "(";
(void) strcpy(buf, "");
if (setting & XAV_FILL) {
(void) strcat(buf, paren);
(void) strcat(buf, "fill");
paren = ",";
}
if (setting & XAV_ENTRY) {
(void) strcat(buf, paren);
(void) strcat(buf, "entry");
paren = ",";
}
if (setting & XAV_TRIGGER) {
(void) strcat(buf, paren);
(void) strcat(buf, "trigger");
paren = ",";
}
if (strcmp(paren, "("))
(void) strcat(buf, ")");
else
(void) strcpy(buf, "(none)");
return buf;
}
static const char *
see_outline(unsigned char setting)
{
static char buf[64];
const char *paren = "(";
(void) strcpy(buf, "");
if (setting & XAO_UNDERLINE) {
(void) strcat(buf, paren);
(void) strcat(buf, "underline");
paren = ",";
}
if (setting & XAO_RIGHT) {
(void) strcat(buf, paren);
(void) strcat(buf, "right");
paren = ",";
}
if (setting & XAO_OVERLINE) {
(void) strcat(buf, paren);
(void) strcat(buf, "overline");
paren = ",";
}
if (setting & XAO_LEFT) {
(void) strcat(buf, paren);
(void) strcat(buf, "left");
paren = ",";
}
if (strcmp(paren, "("))
(void) strcat(buf, ")");
else
(void) strcpy(buf, "(none)");
return buf;
}
const char *
see_efa(unsigned char efa, unsigned char value)
{
static char buf[64];
switch (efa) {
case XA_ALL:
(void) sprintf(buf, " all(%x)", value);
break;
case XA_3270:
(void) sprintf(buf, " 3270%s", see_attr(value));
break;
case XA_VALIDATION:
(void) sprintf(buf, " validation%s", see_validation(value));
break;
case XA_OUTLINING:
(void) sprintf(buf, " outlining(%s)", see_outline(value));
break;
case XA_HIGHLIGHTING:
(void) sprintf(buf, " highlighting(%s)", see_highlight(value));
break;
case XA_FOREGROUND:
(void) sprintf(buf, " foreground(%s)", see_color(value));
break;
case XA_CHARSET:
(void) sprintf(buf, " charset(%x)", value);
break;
case XA_BACKGROUND:
(void) sprintf(buf, " background(%s)", see_color(value));
break;
case XA_TRANSPARENCY:
(void) sprintf(buf, " transparency(%s)", see_transparency(value));
break;
default:
(void) sprintf(buf, " %s[0x%x]", unknown(efa), value);
}
return buf;
}
const char *
see_efa_only(unsigned char efa)
{
switch (efa) {
case XA_ALL:
return "all";
case XA_3270:
return "3270";
case XA_VALIDATION:
return "validation";
case XA_OUTLINING:
return "outlining";
case XA_HIGHLIGHTING:
return "highlighting";
case XA_FOREGROUND:
return "foreground";
case XA_CHARSET:
return "charset";
case XA_BACKGROUND:
return "background";
case XA_TRANSPARENCY:
return "transparency";
default:
return unknown(efa);
}
}
const char *
see_qcode(unsigned char id)
{
static char buf[64];
switch (id) {
case QR_CHARSETS:
return "CharacterSets";
case QR_IMP_PART:
return "ImplicitPartition";
case QR_SUMMARY:
return "Summary";
case QR_USABLE_AREA:
return "UsableArea";
case QR_COLOR:
return "Color";
case QR_HIGHLIGHTING:
return "Highlighting";
case QR_REPLY_MODES:
return "ReplyModes";
case QR_ALPHA_PART:
return "AlphanumericPartitions";
case QR_DDM:
return "DistributedDataManagement";
default:
(void) sprintf(buf, "unknown[0x%x]", id);
return buf;
}
}
/* Data Stream trace print, handles line wraps */
static char *tdsbuf = CN;
#define TDS_LEN 75
static void
trace_ds_s(char *s)
{
int len = strlen(s);
Boolean nl = False;
if (!toggled(DS_TRACE) || !len)
return;
if (s && s[len-1] == '\n') {
len--;
nl = True;
}
while (dscnt + len >= 75) {
int plen = 75-dscnt;
(void) fprintf(tracef, "%.*s ...\n... ", plen, s);
dscnt = 4;
s += plen;
len -= plen;
}
if (len) {
(void) fprintf(tracef, "%.*s", len, s);
dscnt += len;
}
if (nl) {
(void) fprintf(tracef, "\n");
dscnt = 0;
}
}
void
trace_ds(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
/* allocate buffer */
if (tdsbuf == CN)
tdsbuf = Malloc(4096);
/* print out remainder of message */
(void) vsprintf(tdsbuf, fmt, args);
trace_ds_s(tdsbuf);
va_end(args);
}
/* Conditional event trace. */
void
trace_event(const char *fmt, ...)
{
va_list args;
if (!toggled(EVENT_TRACE) || tracef == (FILE *)NULL)
return;
va_start(args, fmt);
/* print out message */
(void) vfprintf(tracef, fmt, args);
va_end(args);
}
#if defined(X3270_DISPLAY) /*[*/
static Widget trace_shell = (Widget)NULL;
#endif
static int trace_reason;
/* Callback for "OK" button on trace popup */
static void
tracefile_callback(Widget w, XtPointer client_data, XtPointer call_data unused)
{
char *tfn;
char *tracecmd;
char *full_cmd;
time_t clk;
Boolean piped = False;
int pipefd[2];
#if defined(X3270_DISPLAY) /*[*/
if (w)
tfn = XawDialogGetValueString((Widget)client_data);
else
#endif /*]*/
tfn = (char *)client_data;
tfn = do_subst(tfn, True, True);
if (strchr(tfn, '\'') ||
((int)strlen(tfn) > 0 && tfn[strlen(tfn)-1] == '\\')) {
popup_an_error("Illegal file name: %s\n", tfn);
Free(tfn);
return;
}
if (!strcmp(tfn, "stdout")) {
tracef = stdout;
} else if (!strcmp(tfn, "none") || !tfn[0]) {
#ifndef AMIGA
if (pipe(pipefd) < 0) {
#else
if (1) {
#endif
popup_an_errno(errno, "pipe() failed");
Free(tfn);
return;
}
tracef = fdopen(pipefd[1], "w");
if (tracef == (FILE *)NULL) {
popup_an_errno(errno, "fdopen() failed");
Free(tfn);
return;
}
(void) SETLINEBUF(tracef);
(void) fcntl(pipefd[1], F_SETFD, 1);
piped = True;
} else {
tracef = fopen(tfn, "a");
if (tracef == (FILE *)NULL) {
popup_an_errno(errno, tfn);
Free(tfn);
return;
}
(void) SETLINEBUF(tracef);
(void) fcntl(fileno(tracef), F_SETFD, 1);
}
/* Start the monitor window */
tracecmd = get_resource(ResTraceCommand);
if (tracecmd == CN || !strcmp(tracecmd, "none") || tracef == stdout)
goto done;
#ifndef AMIGA
switch (tracewindow_pid = fork()) {
case 0: /* child process */
if (piped) {
char cmd[64];
(void) sprintf(cmd, "cat /dev/fd/%d", pipefd[0]);
(void) execlp("xterm", "xterm", "-title", "trace",
"-sb", "-e", "/bin/sh", "-c", cmd, CN);
} else {
full_cmd = xs_buffer("%s <'%s'", tracecmd, tfn);
(void) execlp("xterm", "xterm", "-title", tfn,
"-sb", "-e", "/bin/sh", "-c", full_cmd, CN);
}
(void) perror("exec(xterm)");
_exit(1);
default: /* parent */
if (piped)
(void) close(pipefd[0]);
++children;
break;
case -1: /* error */
popup_an_errno(errno, "fork()");
break;
}
#endif
done:
Free(tfn);
/* Display current status */
clk = time((time_t *)0);
(void) fprintf(tracef, "Trace started %s", ctime(&clk));
(void) fprintf(tracef, " Version: %s\n", build);
save_yourself();
(void) fprintf(tracef, " Command: %s\n", command_string);
(void) fprintf(tracef, " Model %s", model_name);
(void) fprintf(tracef, ", %s display",
appres.mono ? "monochrome" : "color");
if (appres.extended)
(void) fprintf(tracef, ", extended data stream");
if (!appres.mono)
(void) fprintf(tracef, ", %scolor",
appres.m3279 ? "full " : "pseudo-");
if (appres.charset)
(void) fprintf(tracef, ", %s charset", appres.charset);
if (appres.apl_mode)
(void) fprintf(tracef, ", APL mode");
(void) fprintf(tracef, "\n");
if (CONNECTED)
(void) fprintf(tracef, " Connected to %s, port %u\n",
current_host, current_port);
/* We're really tracing, turn the flag on. */
appres.toggle[trace_reason].value = True;
appres.toggle[trace_reason].changed = True;
menubar_retoggle(&appres.toggle[trace_reason]);
#if defined(X3270_DISPLAY) /*[*/
if (w)
XtPopdown(trace_shell);
#endif /*]*/
/* Snap the current TELNET options. */
if (net_snap_options()) {
(void) fprintf(tracef, " TELNET state:\n");
trace_netdata('<', obuf, obptr - obuf);
}
/* Dump the screen contents and modes into the trace file. */
if (CONNECTED) {
/*
* Note that if the screen is not formatted, we do not
* attempt to save what's on it. However, if we're in
* 3270 SSCP-LU or NVT mode, we'll do a dummy, empty
* write to ensure that the display is in the right
* mode.
*/
if (formatted) {
(void) fprintf(tracef, " Screen contents:\n");
obptr = obuf;
#if defined(X3270_TN3270E) /*[*/
(void) net_add_dummy_tn3270e();
#endif /*]*/
ctlr_snap_buffer();
space3270out(2);
net_add_eor(obuf, obptr - obuf);
obptr += 2;
trace_netdata('<', obuf, obptr - obuf);
obptr = obuf;
#if defined(X3270_TN3270E) /*[*/
(void) net_add_dummy_tn3270e();
#endif /*]*/
if (ctlr_snap_modes()) {
(void) fprintf(tracef, " 3270 modes:\n");
space3270out(2);
net_add_eor(obuf, obptr - obuf);
obptr += 2;
trace_netdata('<', obuf, obptr - obuf);
}
}
#if defined(X3270_TN3270E) /*[*/
else if (IN_E) {
obptr = obuf;
if (net_add_dummy_tn3270e()) {
(void) fprintf(tracef,
" Screen contents:\n");
space3270out(2);
net_add_eor(obuf, obptr - obuf);
obptr += 2;
trace_netdata('<', obuf, obptr - obuf);
}
}
#endif /*]*/
}
(void) fprintf(tracef, " Data stream:\n");
}
#if defined(X3270_DISPLAY) /*[*/
/* Callback for "No File" button on trace popup */
static void
no_tracefile_callback(Widget w, XtPointer client_data,
XtPointer call_data unused)
{
tracefile_callback((Widget)NULL, "", PN);
XtPopdown(trace_shell);
}
#endif /*]*/
/* Open the trace file. */
static void
tracefile_on(int reason, enum toggle_type tt)
{
char tracefile_buf[256];
char *tracefile;
if (tracef)
return;
trace_reason = reason;
if (appres.secure) {
tracefile_callback((Widget)NULL, "none", PN);
return;
}
if (appres.trace_file)
tracefile = appres.trace_file;
else {
(void) sprintf(tracefile_buf, "%s/x3trc.%d", appres.trace_dir,
getpid());
tracefile = tracefile_buf;
}
#if defined(X3270_DISPLAY) /*[*/
if (tt == TT_INITIAL)
#endif /*]*/
{
tracefile_callback((Widget)NULL, tracefile, PN);
return;
}
#if defined(X3270_DISPLAY) /*[*/
if (trace_shell == NULL) {
trace_shell = create_form_popup("trace",
tracefile_callback, no_tracefile_callback, FORM_NO_WHITE);
XtVaSetValues(XtNameToWidget(trace_shell, ObjDialog),
XtNvalue, tracefile,
NULL);
}
/* Turn the toggle _off_ until the popup succeeds. */
appres.toggle[reason].value = False;
appres.toggle[reason].changed = True;
popup_popup(trace_shell, XtGrabExclusive);
#endif /*]*/
}
/* Close the trace file. */
static void
tracefile_off(void)
{
time_t clk;
clk = time((time_t *)0);
(void) fprintf(tracef, "Trace stopped %s", ctime(&clk));
if (tracewindow_pid != -1)
#ifndef AMIGA
(void) kill(tracewindow_pid, SIGKILL);
#else
;/* (void) kill(tracewindow_pid, SIGTERM);*/
#endif
tracewindow_pid = -1;
if (tracef != stdout)
(void) fclose(tracef);
tracef = (FILE *) NULL;
}
void
toggle_dsTrace(struct toggle *t unused, enum toggle_type tt)
{
/* If turning on trace and no trace file, open one. */
if (toggled(DS_TRACE) && !tracef)
tracefile_on(DS_TRACE, tt);
/* If turning off trace and not still tracing events, close the
trace file. */
else if (!toggled(DS_TRACE) && !toggled(EVENT_TRACE))
tracefile_off();
if (toggled(DS_TRACE))
(void) gettimeofday(&ds_ts, (struct timezone *)NULL);
}
void
toggle_eventTrace(struct toggle *t unused, enum toggle_type tt)
{
/* If turning on event debug, and no trace file, open one. */
if (toggled(EVENT_TRACE) && !tracef)
tracefile_on(EVENT_TRACE, tt);
/* If turning off event debug, and not tracing the data stream,
close the trace file. */
else if (!toggled(EVENT_TRACE) && !toggled(DS_TRACE))
tracefile_off();
}
/* Screen trace file support. */
#if defined(X3270_DISPLAY) /*[*/
static Widget screentrace_shell = (Widget)NULL;
#endif /*]*/
static FILE *screentracef = (FILE *)0;
/*
* Screen trace function, called when the host clears the screen.
*/
static void
do_screentrace(void)
{
register int i;
if (fprint_screen(screentracef, False)) {
for (i = 0; i < COLS; i++)
(void) fputc('=', screentracef);
(void) fputc('\n', screentracef);
}
}
void
trace_screen(void)
{
trace_skipping = False;
if (!toggled(SCREEN_TRACE) || !screentracef)
return;
do_screentrace();
}
/* Called from ANSI emulation code to log a single character. */
void
trace_char(char c)
{
if (!toggled(SCREEN_TRACE) || !screentracef)
return;
(void) fputc(c, screentracef);
}
/*
* Called when disconnecting in ANSI mode, to finish off the trace file
* and keep the next screen clear from re-recording the screen image.
* (In a gross violation of data hiding and modularity, trace_skipping is
* manipulated directly in ctlr_clear()).
*/
void
trace_ansi_disc(void)
{
int i;
(void) fputc('\n', screentracef);
for (i = 0; i < COLS; i++)
(void) fputc('=', screentracef);
(void) fputc('\n', screentracef);
trace_skipping = True;
}
/*
* Screen tracing callback.
* Returns True for success, False for failure.
*/
static Boolean
screentrace_cb(char *tfn)
{
tfn = do_subst(tfn, True, True);
screentracef = fopen(tfn, "a");
if (screentracef == (FILE *)NULL) {
popup_an_errno(errno, tfn);
Free(tfn);
return False;
}
Free(tfn);
(void) SETLINEBUF(screentracef);
(void) fcntl(fileno(screentracef), F_SETFD, 1);
/* We're really tracing, turn the flag on. */
appres.toggle[SCREEN_TRACE].value = True;
appres.toggle[SCREEN_TRACE].changed = True;
menubar_retoggle(&appres.toggle[SCREEN_TRACE]);
return True;
}
#if defined(X3270_DISPLAY) /*[*/
/* Callback for "OK" button on screentrace popup */
static void
screentrace_callback(Widget w unused, XtPointer client_data,
XtPointer call_data unused)
{
if (screentrace_cb(XawDialogGetValueString((Widget)client_data)))
XtPopdown(screentrace_shell);
}
/* Callback for second "OK" button on screentrace popup */
static void
onescreen_callback(Widget w, XtPointer client_data, XtPointer call_data unused)
{
char *tfn;
if (w)
tfn = XawDialogGetValueString((Widget)client_data);
else
tfn = (char *)client_data;
tfn = do_subst(tfn, True, True);
screentracef = fopen(tfn, "a");
if (screentracef == (FILE *)NULL) {
popup_an_errno(errno, tfn);
XtFree(tfn);
return;
}
(void) fcntl(fileno(screentracef), F_SETFD, 1);
XtFree(tfn);
/* Save the current image, once. */
do_screentrace();
/* Close the file, we're done. */
(void) fclose(screentracef);
screentracef = (FILE *)NULL;
if (w)
XtPopdown(screentrace_shell);
}
#endif /*]*/
void
toggle_screenTrace(struct toggle *t unused, enum toggle_type tt)
{
char tracefile_buf[256];
char *tracefile;
if (toggled(SCREEN_TRACE)) {
if (appres.screentrace_file)
tracefile = appres.screentrace_file;
else {
(void) sprintf(tracefile_buf, "%s/x3scr.%d",
appres.trace_dir, getpid());
tracefile = tracefile_buf;
}
if (tt == TT_INITIAL) {
(void) screentrace_cb(NewString(tracefile));
return;
}
#if defined(X3270_DISPLAY) /*[*/
if (screentrace_shell == NULL) {
screentrace_shell = create_form_popup("screentrace",
screentrace_callback, onescreen_callback,
FORM_NO_WHITE);
XtVaSetValues(XtNameToWidget(screentrace_shell,
ObjDialog),
XtNvalue, tracefile,
NULL);
}
appres.toggle[SCREEN_TRACE].value = False;
appres.toggle[SCREEN_TRACE].changed = True;
popup_popup(screentrace_shell, XtGrabExclusive);
#endif /*]*/
} else {
if (ctlr_any_data() && !trace_skipping)
do_screentrace();
(void) fclose(screentracef);
}
}
#endif /*]*/